home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
comm
/
pipeln10.zip
/
AQUEDUCT.ASM
next >
Wrap
Assembly Source File
|
1990-06-01
|
12KB
|
386 lines
;**************************************************************************
;* AQUEDUCT vers 1.20, DOS *
;* Connects COM1 and COM2 in software. *
;* 6/1/90 *
;* by James W. Birdsall *
;* *
;* assembles under Turbo Assembler 1.0, 2.0 *
;* *
;* requires DOS 2.0 or higher *
;* *
;* This program is a small TSR that connects COM1 and COM2 in software. *
;* It is run from the command line with no arguments. After *
;* installation, setup and activation is performed with the program *
;* VALVE. *
;* *
;* This program can share an interrupt vector. It can be set to chain *
;* to the previous interrupt handler if examination of the serial port *
;* shows that no interrupt is pending. *
;* *
;**************************************************************************
LOCALS
.MODEL tiny
ENVOFFSET EQU 2Ch
INTERFACEINT EQU 0F1h
BUFFERLENGTH EQU 8
BUFFERLENMASK EQU 08h
BUSY1READ EQU 01h
BUSY1SEND EQU 02h
BUSY2READ EQU 04h
BUSY2SEND EQU 08h
; TO CHANGE FROM COM1 OR COM2, CHANGE THE FOLLOWING INTERRUPT AND PORT
; VALUES.
COM1INT EQU 0Ch
COM2INT EQU 0Bh
COM1BASE EQU 3F8h
COM1IER EQU 3F9h
COM1IIR EQU 3FAh
COM1LSR EQU 3FDh
COM2BASE EQU 2F8h
COM2IER EQU 2F9h
COM2IIR EQU 2FAh
COM2LSR EQU 2FDh
; END OF INTERRUPT AND PORT VALUES
EOI EQU 20h
EOIPORT EQU 20h
RDAINT EQU 04h
THREINT EQU 02h
RDAENABLE EQU 01h
BOTHENABLE EQU 03h
OVERRUNMASK EQU 02h
INTPENDMASK EQU 01h
.CODE
ORG 100h
start:
jmp Install ; jump to installation code
; DATA AREA
errors dw 0
int_B dd 0
old_int_B dd 0
int_C dd 0
old_int_C dd 0
PSPseg dw 0
old_interface dd 0
enabled db 0
chain db 0
one_in_head dw 0
one_in_tail dw 0
two_in_head dw 0
two_in_tail dw 0
busyflag db 0
one_in db BUFFERLENGTH dup (?)
two_in db BUFFERLENGTH dup (?)
; HANDLER FOR COM1 INTERRUPTS
Com1handler:
sti ; enable interrupts
push ax ; preserve
push bx
push dx
mov dx, COM1LSR ; check for overruns
in al, dx
test al, OVERRUNMASK
jz @@NoOverrun ; if zero, OK
inc cs:errors ; else increment ERRORS
@@NoOverrun:
mov dx, COM1IIR ; read interrupt id
in al, dx
test al, INTPENDMASK ; is our interrupt?
jz @@Ours ; if zero, ours
jmp @@NotOurs ; else not
@@Ours:
cmp al, RDAINT ; is received char?
je @@Received
cmp al, THREINT ; is send?
je @@Transmit
jmp @@SendEOI ; if unknown, send EOI
@@Received:
mov dx, COM1BASE ; read character
in al, dx
test cs:busyflag, BUSY2SEND ; is port 2 sending?
jz @@OkToRead ; if zero, go ahead
inc cs:errors ; else increment errors
jmp @@SendEOI ; and send EOI
@@OkToRead:
or cs:busyflag, BUSY1READ ; set flag
mov bx, cs:one_in_head ; get index
mov cs:one_in + bx, al ; put char in buffer
inc cs:one_in_head ; increment index
test cs:one_in_head, BUFFERLENMASK ; check for index overflow
jz @@ReadDone ; if no overflow, jump
mov cs:one_in_head, 0 ; else zero index
@@ReadDone:
mov dx, COM2IER ; read interrupt enable
in al, dx
cmp al, BOTHENABLE ; THRE already on?
je @@ReadDone2 ; do nothing
mov al, BOTHENABLE ; else enable it
xor cs:busyflag, BUSY1READ ; reset flag just before enabling int
out dx, al
jmp @@SendEOI ; and jump
@@ReadDone2:
xor cs:busyflag, BUSY1READ ; reset flag
jmp @@SendEOI
@@Transmit:
test cs:busyflag, BUSY2READ ; is port 2 reading?
jz @@OkToSend ; if zero, go ahead
or cs:busyflag, BUSY1SEND
jmp @@NoTrans ; otherwise shut down sending
@@OkToSend:
or cs:busyflag, BUSY1SEND ; set flag
mov bx, cs:two_in_tail ; set index
cmp bx, cs:two_in_head ; are chars to send?
je @@NoTrans ; if not, shut down sending
mov al, cs:two_in + bx ; else move char to AL
mov dx, COM1BASE
out dx, al
inc cs:two_in_tail ; increment index
test cs:two_in_tail, BUFFERLENMASK ; check for overflow
jz @@SentOK ; if no overflow, jump
mov cs:two_in_tail, 0 ; else zero index
@@SentOK:
xor cs:busyflag, BUSY1SEND ; reset flag
jmp @@SendEOI
@@NoTrans:
mov dx, COM1IER ; read interrupt enable
in al, dx
cmp al, RDAENABLE ; RDA only already?
je @@NoTrans2 ; if so, do nothing
mov al, RDAENABLE ; else enable RDA only
out dx, al
jmp @@NoTrans2 ; and jump
@@NoTrans2:
xor cs:busyflag, BUSY1SEND ; reset flag
jmp @@SendEOI ; and jump
@@NotOurs:
test cs:chain, 0FFh ; is chain zero?
jz @@SendEOI ; if so, return normally
pushf ; preserve flags
call cs:old_int_C ; call old handler
jmp @@Final ; and return
@@SendEOI:
mov al, EOI ; send EOI
out EOIPORT, al
@@Final:
pop dx ; restore
pop bx
pop ax
iret ; return
; HANDLER FOR COM2 INTERRUPTS
Com2handler:
sti ; enable interrupts
push ax ; preserve
push bx
push dx
mov dx, COM2LSR ; check for overruns
in al, dx
test al, OVERRUNMASK
jz @@NoOverrun ; if zero, OK
inc cs:errors ; else increment ERRORS
@@NoOverrun:
mov dx, COM2IIR ; read interrupt id
in al, dx
test al, INTPENDMASK ; is our interrupt?
jz @@Ours ; if zero, ours
jmp @@NotOurs ; else not
@@Ours:
cmp al, RDAINT ; is received char?
je @@Received
cmp al, THREINT ; is send?
je @@Transmit
jmp @@SendEOI ; if unknown, send EOI
@@Received:
mov dx, COM2BASE ; read character
in al, dx
test cs:busyflag, BUSY1SEND ; is port 1 sending?
jz @@OkToRead ; if zero, go ahead
inc cs:errors ; else increment errors
jmp @@SendEOI ; and send EOI
@@OkToRead:
or cs:busyflag, BUSY2READ ; set flag
mov bx, cs:two_in_head ; get index
mov cs:two_in + bx, al ; put char in buffer
inc cs:two_in_head ; increment index
test cs:two_in_head, BUFFERLENMASK ; check for index overflow
jz @@ReadDone ; if no overflow, jump
mov cs:two_in_head, 0 ; else zero index
@@ReadDone:
mov dx, COM1IER ; read interrupt enable
in al, dx
cmp al, BOTHENABLE ; THRE already on?
je @@ReadDone2 ; do nothing
mov al, BOTHENABLE ; else enable it
out dx, al
jmp @@ReadDone2 ; and jump
@@ReadDone2:
xor cs:busyflag, BUSY2READ ; reset flag
jmp @@SendEOI ; and jump
@@Transmit:
test cs:busyflag, BUSY1READ ; is port 1 reading?
jz @@OkToSend ; if zero, go ahead
or cs:busyflag, BUSY2SEND ; set flag
jmp @@NoTrans ; otherwise shut down sending
@@OkToSend:
or cs:busyflag, BUSY2SEND ; set flag
mov bx, cs:one_in_tail ; set index
cmp bx, cs:one_in_head ; are chars to send?
je @@NoTrans ; if not, shut down sending
mov al, cs:one_in + bx ; else move char to AL
mov dx, COM2BASE
out dx, al
inc cs:one_in_tail ; increment index
test cs:one_in_tail, BUFFERLENMASK ; check fo